package com.amkai.aes.webservice.binary.objecthandler.inventory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Query;

import com.amkai.aes.aescommon.service.binary.job.inventory.OrderRequisitionsJob;
import com.amkai.aes.aescommon.service.binary.job.inventory.OrderRequisitionsJobResult;
import com.amkai.aes.aescommon.service.binary.job.inventory.PoNumberJobKind;
import com.amkai.aes.aescommon.service.binary.job.inventory.PurchaseNumberData;
import com.amkai.aes.aescommon.service.binary.job.inventory.PurchaseOrderNumberCheckerJob;
import com.amkai.aes.generatedbeans.common.Organization;
import com.amkai.aes.generatedbeans.common.OrganizationContact;
import com.amkai.aes.generatedbeans.inventory.ItemLocation;
import com.amkai.aes.generatedbeans.inventory.purchasing.PurchaseOrder;
import com.amkai.aes.generatedbeans.inventory.purchasing.PurchaseOrderLine;
import com.amkai.aes.generatedbeans.inventory.requisitioning.OrderRequisition;
import com.amkai.aes.generatedbeans.inventory.requisitioning.OrderRequisitionLine;
import com.amkai.aes.generatedbeans.inventory.requisitioning.RequsitionLineStatusKind;
import com.amkai.aes.generatedbeans.inventory.requisitioning.RequsitioningStatusKind;
import com.amkai.aes.server.inventory.PurchaseOrderNumberGenerator;
import com.amkai.aes.server.inventory.RequisitionStatusCalculator;
import com.amkai.aes.server.session.ServiceSessionManager;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;
import com.amkai.rad.designerbase.beans.ChangedKind;


public class OrderRequisitionsHandler implements JobObjectHandler<OrderRequisitionsJob,Serializable, OrderRequisitionsJobResult> {
	
	private static final Exception Exception = null;

	@Override
	public OrderRequisitionsJobResult process(OrderRequisitionsJob job,
			Serializable object) throws Exception {
		// TODO Auto-generated method stub
		switch (job.getJobKind()){
			case SEARCH : return searchRequisitions(job);
			case MODYFY: return null;
			case CREATE_PO: return createPO(job);
		};
		return null;
	}
	
	private OrderRequisitionsJobResult createPO(OrderRequisitionsJob job) throws Exception{
		OrderRequisitionsJobResult result = new OrderRequisitionsJobResult();
		// PurchaseOrder order = domain.getPurchaseOrder();
		String prefX = job.getOrders().iterator().next().getPrefix();
		PurchaseOrderNumberCheckerJob pjob = new PurchaseOrderNumberCheckerJob();
		pjob.setModuleDepartment(job.getModuleDepartment());
		pjob.poData = new PurchaseNumberData();
		pjob.poData.setPrefix(prefX);
		pjob.poData.setKind(PoNumberJobKind.GET_NEW_NUMBER);
		
		//pjob.setModuleDepartment(job.getModuleDepartment());
		PurchaseNumberData pd = PurchaseOrderNumberGenerator.generateData(pjob,null);
		
		SessionManager sm = SiteManager.Start();
		try {
			sm.openSession();
			sm.openTransaction();
			List<Long> createdpos = new ArrayList<Long>();
			
			
			if (pd == null)
				throw Exception;
			Long poId = pd.getGeneratedPONumber();

			int counter = 0;
			for (PurchaseOrder order : job.getOrders()) { // save the po(s)
				counter++;
				order.setPoNumber(poId);
				// savePO(sm, order, job);
				sm.saveRAD(order);
				//OrderRequisition req = order.getOrderRequisition();
				//req.getPurchaseOrders().add(order);
				createdpos.add(order.getPoNumber());
				for (PurchaseOrderLine poLine : order.getPurchaseOrderLines()) {
					poLine.setPurchaseOrder(order);
					poLine.getOrderRequisitionLine().getOrderRequisition().getPurchaseOrders().add(order);
					poLine.getOrderRequisitionLine().getOrderRequisition().setChangedKind(ChangedKind.CHANGED);
					//DP > AES-14612 
					if (poLine.getCreatedBy() == null){
						poLine.setCreatedBy(ServiceSessionManager.getConnection().getRuntimePassport());
					}
					sm.saveRAD(poLine.getOrderRequisitionLine().getOrderRequisition());
					//poLine.setChangedKind(ChangedKind.CHANGED);
					sm.saveRAD(poLine);
					OrderRequisitionLine reqLine = poLine.getOrderRequisitionLine();
					// savePOLine(sm, poLine);
					
					reqLine.getPurchaseOrderLines().add(poLine);
					reqLine.setChangedKind(ChangedKind.CHANGED);
					reqLine.setLineStatus(RequsitionLineStatusKind.ORDERED); // --
					sm.saveRAD(reqLine);
				}
				
				
				
				PurchaseNumberData cpd;
				if (counter < job.getOrders().size()) {
					do {
						poId++;
						PurchaseOrderNumberCheckerJob cpjob = new PurchaseOrderNumberCheckerJob();
						cpjob.poData = new PurchaseNumberData();
						cpjob.poData.setPrefix(prefX);
						cpjob.poData.setKind(PoNumberJobKind.CHECK);
						cpjob.poData.setPonumber(poId);
						cpjob.setModuleDepartment(job.getModuleDepartment());
						cpd = PurchaseOrderNumberGenerator.generateData(cpjob, sm);

					} while (!cpd.getPovalid());
				}

			}
			PurchaseOrderNumberCheckerJob wpj = new PurchaseOrderNumberCheckerJob();
			wpj.poData = new PurchaseNumberData();
			wpj.poData.setKind(PoNumberJobKind.WRITE_BACK_TO_GENERATOR);
			wpj.poData.setPrefix(prefX);
			wpj.poData.setPonumber(poId);
			wpj.setModuleDepartment(job.getModuleDepartment());
			wpj.poData.setOnlysavebywriteback(true);
			PurchaseOrderNumberGenerator.generateData(wpj, sm);

			for (PurchaseOrder order : job.getOrders()) {// --
				List<OrderRequisition> l = RequisitionStatusCalculator.setupRequisisitonStatus(order);
				for(OrderRequisition or : l){
					sm.saveRAD(or);
				}
				//sm.saveRAD(RequisitionStatusCalculator.setupRequisisitonStatus(order.getOrderRequisition()));
			}

			/*
			 * if (job.getRequissitions() != null){ for(OrderRequisition req :
			 * job.getRequissitions()){ //save the requisition(s)
			 * for(OrderRequisitionLine line : req.getOrderRequisitionLines()){
			 * line.setLineStatus(RequsitionLineStatusKind.ORDERED);
			 * line.setChangedKind(ChangedKind.CHANGED); sm.saveRAD(line); }
			 * req.setStatus(RequsitioningStatusKind.ORDERED);
			 * req.setChangedKind(ChangedKind.CHANGED); sm.saveRAD(req);
			 *  } } if (job.getRequisitionLines() != null){ Map<Long,
			 * OrderRequisition> reqs = new HashMap<Long, OrderRequisition>();
			 * for (OrderRequisitionLine line : job.getRequisitionLines()){
			 * line.setLineStatus(RequsitionLineStatusKind.ORDERED);
			 * line.setChangedKind(ChangedKind.CHANGED); sm.saveRAD(line);
			 * OrderRequisition tempreq =
			 * reqs.get(line.getOrderRequisition().getId()); if (tempreq ==
			 * null){ tempreq = sm.get(OrderRequisition.class,
			 * line.getOrderRequisition().getId()); }
			 * tempreq.getOrderRequisitionLines().remove(line);
			 * tempreq.getOrderRequisitionLines().add(line);
			 * reqs.put(tempreq.getId(), tempreq);
			 *  } for (OrderRequisition or : reqs.values() ){
			 * sm.saveRAD(setupRequisitionStatus(or)); } }
			 */

			sm.commitTransaction();
			result.setPoSucessFullyCreated(true);
			result.setCretaedPOS(createdpos);

		} catch (Exception ex) {
			sm.rollbackTransaction();
			ex.printStackTrace();
			throw ex;

		} finally {
			sm.closeSession();
		}
		return result;
	}
	
	private OrderRequisition setupRequisitionStatus(OrderRequisition req){
		Boolean allpending,allcancelled,ordered;
		if (req.getOrderRequisitionLines() != null){
			allcancelled = true;
			ordered = true;
			allpending = true;
			for(OrderRequisitionLine line : req.getOrderRequisitionLines()){
				if (allcancelled)
					allcancelled = line.getLineStatus().equals(RequsitionLineStatusKind.CANCELED);
				if (ordered)
					ordered = line.getLineStatus().equals(RequsitionLineStatusKind.ORDERED)||line.getLineStatus().equals(RequsitionLineStatusKind.RECEIVED)||line.getLineStatus().equals(RequsitionLineStatusKind.PART_RECEIVED)||line.getLineStatus().equals(RequsitionLineStatusKind.BACK_ORDERED)||line.getLineStatus().equals(RequsitionLineStatusKind.CANCELED);
				if (allpending)
					allpending = line.getLineStatus().equals(RequsitionLineStatusKind.PENDING);
			}
			if (!allcancelled && !ordered && !allpending)
				req.setStatus(RequsitioningStatusKind.CONFIRMED);
			else if (allcancelled)
				req.setStatus(RequsitioningStatusKind.CANCELED);
			else if (allpending)
				req.setStatus(RequsitioningStatusKind.PENDING);
			else if (ordered)
				req.setStatus(RequsitioningStatusKind.ORDERED);
		}
		return req;
		
	}
	private OrderRequisitionsJobResult searchRequisitions(OrderRequisitionsJob job) throws Exception{
		// KKORNEL: AES-14658
		String query = "select req " +
				       "from OrderRequisition req " +
				       "left join fetch req.creator " +
				       "where (req.statusWrapper = :status) and (req.baseOrganization.id = :depId) and (size(req.orderRequisitionLines) > 0)";
		String vendorquery = "select vend from Organization vend where vend.id in( select DISTINCT reqline.vendorOrderInformation.vendor.id  from OrderRequisitionLine reqline where reqline.lineStatusWrapper =:status and reqline.orderRequisition.baseOrganization.id = :depId) )";//"select vf from VendorOrderInformation vf left join fetch vf.vendor where vf.vendor.id in( select DISTINCT reqline.vendorOrderInformation.vendor.id  from OrderRequisitionLine reqline where reqline.lineStatusWrapper = :status and reqline.orderRequisition.baseOrganization.id = :depId) ";
		String searchbyvendor = "select reqline from OrderRequisitionLine reqline where reqline.vendorOrderInformation.vendor.id in ( :ids) and reqline.lineStatusWrapper = :status and reqline.orderRequisition.baseOrganization.id = :depId order by reqline.vendorOrderInformation.id";
		switch (job.getSearchType()) {
		case SEARCH_BY_REQUISIITON: {
			SessionManager sm = SiteManager.Start();
			
			try {
				sm.openSession();
				Query q;
				q = sm.execute(query);
				q = q.setLong("depId", job.getModuleDepartment().getId());
				q.setInteger("status", job.getRequisitionStatus().ordinal());
				OrderRequisitionsJobResult result = new OrderRequisitionsJobResult();
				List<OrderRequisition> reqs = q.list(); 
				if (!reqs.equals(null) ){
					for(OrderRequisition req : reqs){
						if (req.getPurchaseOrders() != null){
							for(PurchaseOrder od: req.getPurchaseOrders()){
								od.getPoNumber();
							}
						}
						if(!req.getOrderRequisitionLines().equals(null)){
							for(OrderRequisitionLine reqLine : req.getOrderRequisitionLines()){
								if (!reqLine.getVendorOrderInformation().getInventoryElement().equals(null)){
									reqLine.getVendorOrderInformation().getUsageUnitPerOrderingUnit();
									if (reqLine.getPurchaseOrderLines() != null){
										for(PurchaseOrderLine pline : reqLine.getPurchaseOrderLines()){
											pline.getId();
										}
									}
									for (ItemLocation itl : reqLine.getVendorOrderInformation().getInventoryElement().getItemLocations()){
										itl.getDefaultLocation();
									}
									if (!reqLine.getVendorOrderInformation().getVendor().equals(null)){
										reqLine.getVendorOrderInformation().getVendor().getDescription();
										if (reqLine.getVendorOrderInformation().getVendor().getOrganizationContacts() != null){
											for(OrganizationContact ogc : reqLine.getVendorOrderInformation().getVendor().getOrganizationContacts()){
												ogc.getComment();	
											}	
										}
									}	
									reqLine.getVendorOrderInformation().getPricePerOrderingUnit();
									if (!reqLine.getVendorOrderInformation().getInventoryElement().getSupplyResourceItem().equals(null)){
										reqLine.getVendorOrderInformation().getInventoryElement().getSupplyResourceItem().getName();
									}
									
								}
							}
						}
					}
				}
				
				result.setRequisitions(reqs);
				return result;
			} catch (Exception e) {
				e.printStackTrace();
				
			} finally {
				sm.closeSession();
			}			
		}
			
		case SEARCH_VENDOR:
		{
			SessionManager sm = SiteManager.Start();
			try {
				sm.openSession();
				Query q;
				q = sm.execute(vendorquery);
				q = q.setLong("depId", job.getModuleDepartment().getId());
				q.setInteger("status", job.getRequisitionStatus().ordinal());
				OrderRequisitionsJobResult result = new OrderRequisitionsJobResult();
				List<Organization> reqs = q.list(); 
				result.setVendors(reqs);
				return result;
			} catch (Exception e) {
				e.printStackTrace();
				
			} finally {
				sm.closeSession();
			}		
			
			
		}
		case SEARCH_REQUISITION_BY_VENDOR:{
			OrderRequisitionsJobResult result = new OrderRequisitionsJobResult();
			SessionManager sm = SiteManager.Start();
			try {
				sm.openSession();
				Query q;
				q = sm.execute(searchbyvendor);
				q.setLong("depId", job.getModuleDepartment().getId());
				q.setParameterList("ids", job.getVendorIds());
				q.setInteger("status", job.getRequisitionStatus().ordinal());
				List<OrderRequisitionLine> res = q.list();
				if (res != null) {
					for(OrderRequisitionLine line : res){
							if (line.getOrderRequisition() != null){
								for(OrderRequisitionLine oline : line.getOrderRequisition().getOrderRequisitionLines()){
									oline.getLineStatus();
								}
								line.getOrderRequisition().getCreated().getDate();
								line.getOrderRequisition().getCreator().getName();
								line.getOrderRequisition().getBaseOrganization().getId();
								if (line.getOrderRequisition().getPurchaseOrders() != null){
									for(PurchaseOrder od: line.getOrderRequisition().getPurchaseOrders()){
										od.getPoNumber();
									}
								}
							}
							if (!line.getVendorOrderInformation().getInventoryElement().equals(null)){
								line.getVendorOrderInformation().getUsageUnitPerOrderingUnit();
								if (line.getPurchaseOrderLines() != null){
									for(PurchaseOrderLine pline : line.getPurchaseOrderLines()){
										pline.getId();
									}
								}
								for (ItemLocation itl : line.getVendorOrderInformation().getInventoryElement().getItemLocations()){
									itl.getDefaultLocation();
								}
								if (!line.getVendorOrderInformation().getVendor().equals(null)){
									line.getVendorOrderInformation().getVendor().getDescription();
									if (line.getVendorOrderInformation().getVendor().getOrganizationContacts() != null){
										for(OrganizationContact ogc : line.getVendorOrderInformation().getVendor().getOrganizationContacts()){
											ogc.getComment();	
										}	
									}
								}	
								line.getVendorOrderInformation().getPricePerOrderingUnit();
								if (!line.getVendorOrderInformation().getInventoryElement().getSupplyResourceItem().equals(null)){
									line.getVendorOrderInformation().getInventoryElement().getSupplyResourceItem().getName();
								}
								
							
						
						}
						
					}
					result.setRequisitionLines(res);
					return result;
				}
				
			} catch (Exception e) {
				e.printStackTrace();
				
			} finally {
				sm.closeSession();
			}			
			
		}
		
		
		
		
		}
		return null;
	}
	private void savePO(SessionManager sm,PurchaseOrder order) throws Exception{
		/*if (sm.equals(null)){
			SessionManager asm = SiteManager.Start();
			//PurchaseOrder order = domain.getPurchaseOrder();
			try {
				asm.saveRAD(order);
					
				sm.commitTransaction();
			} catch (Exception ex) {
				sm.rollbackTransaction();
				ex.printStackTrace();
				throw ex;
			} finally {
				sm.closeSession();
			}
			
		}else*/
		
		sm.saveRAD(order);
		
	}
	
	
	
	private void savePOLine(SessionManager sm ,PurchaseOrderLine line) throws Exception{
		/*if (sm.equals(null)){
			SessionManager asm = SiteManager.Start();
			//PurchaseOrder order = domain.getPurchaseOrder();
			try {
				asm.saveRAD(line);
					
				sm.commitTransaction();
			} catch (Exception ex) {
				sm.rollbackTransaction();
				ex.printStackTrace();
				throw ex;
			} finally {
				sm.closeSession();
			}
		
		}else*/
			sm.saveRAD(line);
		
	}

	


}
